package com.ruoyi.web.controller.dashboard;

import java.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.repair.service.ITFaultReportService;
import com.ruoyi.repair.service.ITWorkOrderService;
import com.ruoyi.repair.domain.TFaultReport;
import com.ruoyi.repair.domain.TWorkOrder;
import com.ruoyi.report.service.ITRptOrderService;
import com.ruoyi.report.domain.TRptOrder;
import com.ruoyi.asset.service.ITAssetService;
import com.ruoyi.inventory.service.ITSpPartService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.dict.service.ITDictFaultTypeService;
import com.ruoyi.dict.domain.TDictFaultType;
import com.ruoyi.common.utils.DateUtils;

/**
 * 统计看板控制器
 * 
 * @author ruoyi
 * @date 2025-01-15
 */
@RestController
@RequestMapping("/dashboard")
public class DashboardController extends BaseController
{
    @Autowired
    private ITFaultReportService faultReportService;
    
    @Autowired
    private ITRptOrderService rptOrderService;
    
    @Autowired
    private ITWorkOrderService workOrderService;
    
    @Autowired
    private ITAssetService assetService;
    
    @Autowired
    private ITSpPartService partService;
    
    @Autowired
    private ISysUserService userService;
    
    @Autowired
    private ITDictFaultTypeService dictFaultTypeService;

    /**
     * 获取故障类型列表
     */
    @GetMapping("/fault-types")
    public AjaxResult getFaultTypes()
    {
        try {
            TDictFaultType query = new TDictFaultType();
            query.setEnabled(1L);
            query.setIsDelete(0);
            List<TDictFaultType> faultTypes = dictFaultTypeService.selectTDictFaultTypeList(query);
            
            List<Map<String, Object>> data = new ArrayList<>();
            for (TDictFaultType faultType : faultTypes) {
                Map<String, Object> item = new HashMap<>();
                item.put("label", faultType.getName());
                item.put("value", faultType.getName());
                data.add(item);
            }
            
            return AjaxResult.success(data);
        } catch (Exception e) {
            logger.error("获取故障类型列表失败", e);
            return AjaxResult.error("获取故障类型列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取关键指标数据
     */
    @GetMapping("/metrics")
    public AjaxResult getMetrics()
    {
        try {
            logger.info("开始获取关键指标数据");
            Map<String, Object> metrics = new HashMap<>();
            
            // 累计完成维修数量
            int completedRepairs = getCompletedRepairsCount();
            logger.info("累计完成维修数量: {}", completedRepairs);
            metrics.put("completedRepairs", completedRepairs);
            
            // 维修中数量
            int repairing = getRepairingCount();
            logger.info("维修中数量: {}", repairing);
            metrics.put("repairing", repairing);
            
            // 追加工中数量
            int reworking = getReworkingCount();
            logger.info("追加工中数量: {}", reworking);
            metrics.put("reworking", reworking);
            
            // 待料中数量
            int waitingForMaterial = getWaitingForMaterialCount();
            logger.info("待料中数量: {}", waitingForMaterial);
            metrics.put("waitingForMaterial", waitingForMaterial);
            
            logger.info("关键指标数据获取完成: {}", metrics);
            return AjaxResult.success(metrics);
        } catch (Exception e) {
            logger.error("获取关键指标数据失败", e);
            return AjaxResult.error("获取数据失败: " + e.getMessage());
        }
    }

    /**
     * 获取故障类型分布数据
     */
    @GetMapping("/fault-type-distribution")
    public AjaxResult getFaultTypeDistribution()
    {
        try {
            logger.info("开始获取故障类型分布数据");
            
            // 首先获取字典表中定义的故障类型
            TDictFaultType query = new TDictFaultType();
            query.setEnabled(1L);
            query.setIsDelete(0);
            List<TDictFaultType> dictFaultTypes = dictFaultTypeService.selectTDictFaultTypeList(query);
            logger.info("字典表中故障类型数量: {}", dictFaultTypes.size());
            
            // 初始化故障类型统计
            Map<String, Integer> faultTypeCount = new HashMap<>();
            for (TDictFaultType dictType : dictFaultTypes) {
                faultTypeCount.put(dictType.getName(), 0);
            }
            
            // 查询 t_fault_report 表
            TFaultReport query1 = new TFaultReport();
            List<TFaultReport> faultReports = faultReportService.selectTFaultReportList(query1);
            logger.info("t_fault_report表查询结果数量: {}", faultReports.size());
            for (TFaultReport report : faultReports) {
                String faultType = report.getFaultTypeName();
                if (faultType != null && !faultType.isEmpty() && faultTypeCount.containsKey(faultType)) {
                    faultTypeCount.put(faultType, faultTypeCount.get(faultType) + 1);
                }
            }
            
            // 查询 t_rpt_order 表
            TRptOrder query2 = new TRptOrder();
            List<TRptOrder> rptOrders = rptOrderService.selectTRptOrderList(query2);
            logger.info("t_rpt_order表查询结果数量: {}", rptOrders.size());
            for (TRptOrder order : rptOrders) {
                String faultTypeCode = order.getFaultTypeCode();
                if (faultTypeCode != null && !faultTypeCode.isEmpty()) {
                    String faultTypeName = convertFaultTypeCodeToName(faultTypeCode);
                    if (faultTypeName != null && faultTypeCount.containsKey(faultTypeName)) {
                        faultTypeCount.put(faultTypeName, faultTypeCount.get(faultTypeName) + 1);
                    }
                }
            }
            
            logger.info("故障类型统计结果: {}", faultTypeCount);
            
            // 转换为前端需要的格式
            List<Map<String, Object>> data = new ArrayList<>();
            for (Map.Entry<String, Integer> entry : faultTypeCount.entrySet()) {
                data.add(createFaultTypeData(entry.getKey(), entry.getValue()));
            }
            
            logger.info("故障类型分布数据获取完成: {}", data);
            return AjaxResult.success(data);
        } catch (Exception e) {
            logger.error("获取故障类型分布数据失败", e);
            return AjaxResult.error("获取数据失败: " + e.getMessage());
        }
    }

    /**
     * 获取近30天报修次数趋势数据
     */
    @GetMapping("/repair-count-trend")
    public AjaxResult getRepairCountTrend()
    {
        try {
            List<String> dates = new ArrayList<>();
            List<Integer> counts = new ArrayList<>();
            
            // 生成最近30天的数据
            for (int i = 29; i >= 0; i--) {
                Date date = DateUtils.addDays(new Date(), -i);
                dates.add(DateUtils.parseDateToStr("MM/dd", date));
                counts.add(getRepairCountByDate(date));
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("dates", dates);
            result.put("counts", counts);
            
            return AjaxResult.success(result);
        } catch (Exception e) {
            logger.error("获取报修次数趋势数据失败", e);
            return AjaxResult.error("获取数据失败");
        }
    }

    /**
     * 获取维修工平均时长统计数据
     */
    @GetMapping("/repair-duration-stats")
    public AjaxResult getRepairDurationStats(
            @RequestParam(required = false) String faultType,
            @RequestParam(required = false, defaultValue = "week") String timeRange)
    {
        try {
            // 查询维修单数据
            TWorkOrder query = new TWorkOrder();
            query.setIsDelete(0);
            
            // 获取所有维修单，然后在内存中按时间范围筛选
            List<TWorkOrder> allWorkOrders = workOrderService.selectTWorkOrderList(query);
            List<TWorkOrder> workOrders = new ArrayList<>();
            
            // 根据时间范围和故障类型筛选
            Date startDate = getStartDateByRange(timeRange);
            for (TWorkOrder order : allWorkOrders) {
                boolean timeMatch = true;
                boolean faultTypeMatch = true;
                
                // 时间筛选
                if (startDate != null && order.getCreatedAt() != null) {
                    timeMatch = order.getCreatedAt().after(startDate);
                }
                
                // 故障类型筛选
                if (faultType != null && !faultType.isEmpty() && !"全部".equals(faultType)) {
                    // 通过工单的rpt_no关联故障报告来筛选故障类型
                    if (order.getRptNo() != null && !order.getRptNo().isEmpty()) {
                        try {
                            // 查询对应的故障报告
                            TFaultReport faultReport = faultReportService.selectTFaultReportByReportNo(order.getRptNo());
                            if (faultReport != null) {
                                String reportFaultType = faultReport.getFaultTypeName();
                                if (reportFaultType != null) {
                                    // 将故障类型名称转换为编码进行匹配
                                    String faultTypeCode = convertFaultTypeNameToCode(faultType);
                                    faultTypeMatch = reportFaultType.equals(faultType) || 
                                                   (faultTypeCode != null && faultTypeCode.equals(faultReport.getFaultType()));
                                } else {
                                    faultTypeMatch = false;
                                }
                            } else {
                                faultTypeMatch = false;
                            }
                        } catch (Exception e) {
                            logger.warn("查询故障报告失败: {}", order.getRptNo(), e);
                            faultTypeMatch = false;
                        }
                    } else {
                        faultTypeMatch = false;
                    }
                }
                
                if (timeMatch && faultTypeMatch) {
                    workOrders.add(order);
                }
            }
            
            logger.info("维修工平均时长统计 - 故障类型: {}, 时间范围: {}, 筛选后工单数量: {}", faultType, timeRange, workOrders.size());
            
            // 统计维修工平均时长 - 优先使用assignee_id，为空则使用leader_id，都为空则使用-1表示未分配
            Map<Long, List<Double>> repairmanDurations = new HashMap<>();
            for (TWorkOrder order : workOrders) {
                if (order.getStartTime() != null && order.getEndTime() != null) {
                    Long userId = order.getAssigneeId();
                    if (userId == null) {
                        userId = order.getLeaderId(); // 如果assignee_id为空，使用leader_id
                    }
                    if (userId == null) {
                        userId = -1L; // 都为空时使用-1表示未分配
                    }
                    long duration = order.getEndTime().getTime() - order.getStartTime().getTime();
                    double hours = duration / (1000.0 * 60 * 60); // 转换为小时
                    
                    repairmanDurations.computeIfAbsent(userId, k -> new ArrayList<>()).add(hours);
                }
            }
            
            // 计算平均时长并转换为前端格式
            List<Map<String, Object>> data = new ArrayList<>();
            for (Map.Entry<Long, List<Double>> entry : repairmanDurations.entrySet()) {
                Long userId = entry.getKey();
                List<Double> durations = entry.getValue();
                
                double avgDuration = durations.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
                
                // 获取用户名称
                String userName = getUserNameById(userId);
                data.add(createRepairmanData(userName, avgDuration));
            }
            
            // 不再返回占位的“暂无数据”，保持空数组给前端自行处理
            
            return AjaxResult.success(data);
        } catch (Exception e) {
            logger.error("获取维修工平均时长统计数据失败", e);
            return AjaxResult.error("获取数据失败");
        }
    }

    /**
     * 获取维修工维修次数统计数据
     */
    @GetMapping("/repair-count-stats")
    public AjaxResult getRepairCountStats(
            @RequestParam(required = false) String faultType,
            @RequestParam(required = false, defaultValue = "week") String timeRange)
    {
        try {
            // 查询维修单数据
            TWorkOrder query = new TWorkOrder();
            query.setIsDelete(0);
            
            // 获取所有维修单，然后在内存中按时间范围筛选
            List<TWorkOrder> allWorkOrders = workOrderService.selectTWorkOrderList(query);
            List<TWorkOrder> workOrders = new ArrayList<>();
            
            // 根据时间范围和故障类型筛选
            Date startDate = getStartDateByRange(timeRange);
            for (TWorkOrder order : allWorkOrders) {
                boolean timeMatch = true;
                boolean faultTypeMatch = true;
                
                // 时间筛选
                if (startDate != null && order.getCreatedAt() != null) {
                    timeMatch = order.getCreatedAt().after(startDate);
                }
                
                // 故障类型筛选
                if (faultType != null && !faultType.isEmpty() && !"全部".equals(faultType)) {
                    // 通过工单的rpt_no关联故障报告来筛选故障类型
                    if (order.getRptNo() != null && !order.getRptNo().isEmpty()) {
                        try {
                            // 查询对应的故障报告
                            TFaultReport faultReport = faultReportService.selectTFaultReportByReportNo(order.getRptNo());
                            if (faultReport != null) {
                                String reportFaultType = faultReport.getFaultTypeName();
                                if (reportFaultType != null) {
                                    // 将故障类型名称转换为编码进行匹配
                                    String faultTypeCode = convertFaultTypeNameToCode(faultType);
                                    faultTypeMatch = reportFaultType.equals(faultType) || 
                                                   (faultTypeCode != null && faultTypeCode.equals(faultReport.getFaultType()));
                                } else {
                                    faultTypeMatch = false;
                                }
                            } else {
                                faultTypeMatch = false;
                            }
                        } catch (Exception e) {
                            logger.warn("查询故障报告失败: {}", order.getRptNo(), e);
                            faultTypeMatch = false;
                        }
                    } else {
                        faultTypeMatch = false;
                    }
                }
                
                if (timeMatch && faultTypeMatch) {
                    workOrders.add(order);
                }
            }
            
            logger.info("维修工维修次数统计 - 故障类型: {}, 时间范围: {}, 筛选后工单数量: {}", faultType, timeRange, workOrders.size());
            
            // 统计维修工维修次数 - 优先使用assignee_id，为空则使用leader_id，都为空则使用-1表示未分配
            Map<Long, Integer> repairmanCounts = new HashMap<>();
            for (TWorkOrder order : workOrders) {
                Long userId = order.getAssigneeId();
                if (userId == null) {
                    userId = order.getLeaderId(); // 如果assignee_id为空，使用leader_id
                }
                if (userId == null) {
                    userId = -1L; // 都为空时使用-1表示未分配
                }
                repairmanCounts.put(userId, 
                    repairmanCounts.getOrDefault(userId, 0) + 1);
            }
            
            // 转换为前端格式
            List<Map<String, Object>> data = new ArrayList<>();
            for (Map.Entry<Long, Integer> entry : repairmanCounts.entrySet()) {
                Long userId = entry.getKey();
                Integer count = entry.getValue();
                
                // 获取用户名称
                String userName = getUserNameById(userId);
                data.add(createRepairmanCountData(userName, count));
            }
            
            // 不再返回占位的“暂无数据”，保持空数组给前端自行处理
            
            return AjaxResult.success(data);
        } catch (Exception e) {
            logger.error("获取维修工维修次数统计数据失败", e);
            return AjaxResult.error("获取数据失败");
        }
    }

    /**
     * 获取所有统计数据
     */
    @GetMapping("/all-statistics")
    public AjaxResult getAllStatistics()
    {
        try {
            Map<String, Object> result = new HashMap<>();
            
            // 获取关键指标
            AjaxResult metricsResult = getMetrics();
            if (metricsResult.get("code").equals(200)) {
                result.put("metrics", metricsResult.get("data"));
            }
            
            // 获取故障类型分布
            AjaxResult faultTypeResult = getFaultTypeDistribution();
            if (faultTypeResult.get("code").equals(200)) {
                result.put("faultTypeDistribution", faultTypeResult.get("data"));
            }
            
            // 获取报修趋势
            AjaxResult trendResult = getRepairCountTrend();
            if (trendResult.get("code").equals(200)) {
                result.put("repairTrend", trendResult.get("data"));
            }
            
            return AjaxResult.success(result);
        } catch (Exception e) {
            logger.error("获取所有统计数据失败", e);
            return AjaxResult.error("获取数据失败");
        }
    }

    // 私有辅助方法
    
    private int getCompletedRepairsCount() {
        try {
            TWorkOrder query = new TWorkOrder();
            query.setStatusCode("DONE"); // 已结束
            query.setIsDelete(0);
            List<TWorkOrder> completedOrders = workOrderService.selectTWorkOrderList(query);
            return completedOrders.size();
        } catch (Exception e) {
            logger.error("获取已完成维修数量失败", e);
            return 0;
        }
    }
    
    private int getRepairingCount() {
        try {
            // 维修中口径：含 待维修(PENDING_EXEC) / 执行中(IN_PROGRESS) / 待料中(WAITING_MATERIAL) / 追加工中(EXTRA_PROCESSING)
            int total = 0;
            String[] repairingStatuses = new String[]{"PENDING_EXEC", "IN_PROGRESS", "WAITING_MATERIAL", "EXTRA_PROCESSING"};
            for (String s : repairingStatuses) {
                TWorkOrder query = new TWorkOrder();
                query.setStatusCode(s);
                query.setIsDelete(0);
                List<TWorkOrder> list = workOrderService.selectTWorkOrderList(query);
                total += (list == null ? 0 : list.size());
            }
            return total;
        } catch (Exception e) {
            logger.error("获取维修中数量失败", e);
            return 0;
        }
    }
    
    private int getReworkingCount() {
        try {
            TWorkOrder query = new TWorkOrder();
            // 追加工中的状态码应为 EXTRA_PROCESSING（前端与列表页一致）
            query.setStatusCode("EXTRA_PROCESSING");
            query.setIsDelete(0);
            List<TWorkOrder> reworkingOrders = workOrderService.selectTWorkOrderList(query);
            return reworkingOrders.size();
        } catch (Exception e) {
            logger.error("获取追加工中数量失败", e);
            return 0;
        }
    }
    
    private int getWaitingForMaterialCount() {
        try {
            TWorkOrder query = new TWorkOrder();
            query.setStatusCode("WAITING_MATERIAL"); // 待料中
            query.setIsDelete(0);
            List<TWorkOrder> waitingOrders = workOrderService.selectTWorkOrderList(query);
            return waitingOrders.size();
        } catch (Exception e) {
            logger.error("获取待料中数量失败", e);
            return 0;
        }
    }
    
    private int getRepairCountByDate(Date date) {
        try {
            int count = 0;
            
            // 仅统计“故障报修”创建量，且排除逻辑删除
            TFaultReport query1 = new TFaultReport();
            List<TFaultReport> allReports = faultReportService.selectTFaultReportList(query1);
            String targetDateStr = DateUtils.parseDateToStr("yyyy-MM-dd", date);
            
            for (TFaultReport report : allReports) {
                if (report.getCreateTime() != null) {
                    String reportDateStr = DateUtils.parseDateToStr("yyyy-MM-dd", report.getCreateTime());
                    if (targetDateStr.equals(reportDateStr)) {
                        count++;
                    }
                }
            }
            
            logger.info("日期 {} 的报修数量: {}", targetDateStr, count);
            return count;
        } catch (Exception e) {
            logger.error("获取指定日期报修数量失败: " + date, e);
            return 0;
        }
    }
    
    private Map<String, Object> createFaultTypeData(String name, int value) {
        Map<String, Object> data = new HashMap<>();
        data.put("name", name);
        data.put("value", value);
        return data;
    }
    
    private Map<String, Object> createRepairmanData(String name, double duration) {
        Map<String, Object> data = new HashMap<>();
        data.put("name", name);
        data.put("duration", duration);
        return data;
    }
    
    private Map<String, Object> createRepairmanCountData(String name, int count) {
        Map<String, Object> data = new HashMap<>();
        data.put("name", name);
        data.put("count", count);
        return data;
    }
    
    /**
     * 根据时间范围获取开始日期
     */
    private Date getStartDateByRange(String timeRange) {
        Date now = new Date();
        switch (timeRange) {
            case "week":
                return DateUtils.addDays(now, -7); // 恢复为7天
            case "month":
                return DateUtils.addMonths(now, -1);
            case "year":
                return DateUtils.addYears(now, -1);
            default:
                return DateUtils.addDays(now, -7); // 默认7天
        }
    }
    
    /**
     * 根据用户ID获取用户名称
     */
    private String getUserNameById(Long userId) {
        try {
            if (userId == null) {
                return "未知用户";
            }
            if (userId == -1L) {
                return "未分配";
            }
            // 调用用户服务获取用户名称
            try {
                SysUser user = userService.selectUserById(userId);
                if (user != null) {
                    return user.getNickName() != null ? user.getNickName() : user.getUserName();
                }
            } catch (Exception e) {
                logger.warn("获取用户信息失败: " + userId, e);
            }
            return "用户" + userId;
        } catch (Exception e) {
            logger.error("获取用户名称失败: " + userId, e);
            return "未知用户";
        }
    }
    
    /**
     * 将故障类型编码转换为名称
     */
    private String convertFaultTypeCodeToName(String code) {
        if (code == null || code.isEmpty()) {
            return "未分类";
        }
        
        try {
            TDictFaultType faultType = dictFaultTypeService.selectTDictFaultTypeByCode(code);
            if (faultType != null && faultType.getEnabled() == 1) {
                return faultType.getName();
            }
        } catch (Exception e) {
            logger.warn("查询故障类型失败: {}", code, e);
        }
        
        return code; // 如果查询失败，直接返回编码
    }
    
    /**
     * 将故障类型名称转换为编码
     */
    private String convertFaultTypeNameToCode(String name) {
        if (name == null || name.isEmpty()) {
            return null;
        }
        
        try {
            TDictFaultType query = new TDictFaultType();
            query.setName(name);
            query.setEnabled(1L);
            query.setIsDelete(0);
            List<TDictFaultType> faultTypes = dictFaultTypeService.selectTDictFaultTypeList(query);
            if (!faultTypes.isEmpty()) {
                return faultTypes.get(0).getCode();
            }
        } catch (Exception e) {
            logger.warn("查询故障类型失败: {}", name, e);
        }
        
        return null;
    }
}
